const { db } = require('../schema/config')
const userSchema = require('../schema/user')
const crypto = require('../utils/encrypt')

// 创建一个控制user表的模型对象
const User = db.model("users", userSchema)

// 导出用户登录触发的中间件
exports.login = async (ctx) => {
  // 拿到用户请求的表单信息
  const userData = ctx.request.body
  const username = userData.username
  const password = userData.password

  // 查询数据库user是否存在
  await new Promise((resolve, reject) => {
    User.find({username}, (err, data) => {
      if (err) {
        return reject(err)
      }
      if (data.length === 0) {
        // 用户不存在
        return reject("登录失败，用户不存在")
      }
      if (data[0].password === crypto(password)) {
        // 密码正确
        return resolve(data)
      }
      resolve("")
    })
  })
  .then(async data => {
    if (!data) {
      // data为空执行
      return ctx.render("isOk", {
        status: "登录失败，密码错误"
      })
    }

    // 在登录成功之前判断session信息
    ctx.cookies.set("username", username, { // (键名, 键值)
      domain: "localhost",
      path: "/",
      maxAge: 36e5,
      httpOnly: false,
      overwrite: false
    }) 

    // 用户在数据库的id值
    ctx.cookies.set("uid", data[0]._id, { // (键名, 键值)
      domain: "localhost",
      path: "/",
      maxAge: 36e5,
      httpOnly: false,
      overwrite: false
    }) 

    ctx.session = {
      username,
      uid: data[0]._id,
      avatar: data[0].avatar
    }

    await ctx.render("isOk", {
      status: "登陆成功"
    })
  })
  .catch(async err => {
    await ctx.render("isOk", {
      status: err
    })
  })
}

// 导出用户注册触发的中间件
exports.reg = async (ctx) => {
  // 拿到用户请求的表单信息
  const userData = ctx.request.body
  const username = userData.username
  const password = userData.password

  // 去数据库的user表查询用户名是否存在
  await new Promise((resolve, reject) => {
    // 因为find是一个异步操作，所以必须使用await，而await后面必须是Promise对象，因此find需要写在Promise对象内部
    User.find({username}, (err, data) => {
      if (err) {
        return reject(err)
      }
      if (data.length !== 0) {
        // 用户名已存在
        return resolve("")
      }
      /**
       * 用户名不存在，即数据库中username为空
       * 数据存入数据库之前需要加密，需要使用原生的encrypt模块加密
       * 对模型对象实例化
       */
      const userObj = new User({
        username,
        password:crypto(password)
      })
      // 将加密之后的用户对象存入数据库
      userObj.save((err, data) => {
        if (err) {
          // 保存失败
          reject(err)
        } else {
          resolve(data)
        }
      })



    })
  })
  // resolve时触发then
  .then(async data => {
    if (data) {
      // 用户名保存成功
      await ctx.render("isOk", {
        status: "注册成功"
      })
    } else {
      // 用户名已存在
      await ctx.render("isOk", {
        status: "注册失败，用户名已存在"
      })
    }
  })
  // reject时触发catch
  .catch(async err => {
    // 注册失败或者加密保存失败
    await ctx.render("isOk", {
      status: "注册失败，请重试"
    })
  })
}

// 导出一个保持用户状态的中间件
exports.keepLog = async (ctx, next) => {
  // 判断用户是否登陆过，即判断session是否存在
  if (ctx.session.isNew) {
    // 用户未登录
    if (ctx.cookies.get("username")) {
      // 如果存在cookie则更新一下session
      ctx.session = {
        username: ctx.cookies.get("username"),
        uid: ctx.cookies.get("uid")
      }
    }
  } 
  await next()
}

// 导出用户退出登录中间件
exports.logout = async (ctx) => {
  // 让session和cookie过期
  ctx.session = null
  ctx.cookies.set("username", null)
  ctx.cookies.set("uid", null)
  // 重定向到首页
  ctx.redirect("/")
}
